#ifndef __HELPER_H__
#define __HELPER_H__

#include "rpc.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// Valid check
int valid_name(const char* name) {
    // return 1 if valid, 0 otherwise
    if(name == NULL)
        return 0;

    int length = strlen(name);
    if(length == 0 || length >= 2000)
        return 0;

    return 1;
}


// List Node Interface

typedef struct LNode  LNode;
typedef struct LNode* PLNode;

struct LNode {
    int id;
    char* name;
    rpc_handler handler;
    PLNode next;
};

PLNode create_dummy_head() {
    PLNode node = (PLNode)malloc(sizeof(LNode));
    node->handler = NULL;
    node->name = NULL;
    node->id = -1;
    node->next = NULL;
    return node;
}

void insert(PLNode head, PLNode node) {
    node->next = head->next;
    head->next = node;
}

PLNode find_node_by_name(PLNode head, const char* name) {
    PLNode ptr = head->next;
    while(ptr) {
        if(strcmp(name, ptr->name) == 0) {
            return ptr;
        }
        ptr = ptr->next;
    }
    return NULL;
}

PLNode find_node_by_id(PLNode head, int id) {
    PLNode ptr = head->next;
    while(ptr) {
        if(id == ptr->id) {
            return ptr;
        }
        ptr = ptr->next;
    }
    return NULL;
}

void node_register(PLNode head, int id, const char* name, rpc_handler handler) {
    PLNode node = find_node_by_name(head, name);
    if(node == NULL) {
        // insert a node
        node = (PLNode)malloc(sizeof(LNode));
        node->name = (char*)malloc(strlen(name) + 1);
        strcpy(node->name, name);
        node->id = id;
        node->handler = handler;
        insert(head, node);
    }else {
        // update a node
        node->id = id;
        node->handler = handler;
    }
}

void print_list(PLNode head) {
    PLNode ptr = head->next;
    while(ptr) {
        printf("function name: %s, id: %d, handler va: %p\n", ptr->name, ptr->id, ptr->handler);
        ptr = ptr->next;
    }
}

void free_node(PLNode node) {
    if(node->name)
        free(node->name);
    if(node)
        free(node);
}

void free_list(PLNode head) {
    PLNode ptr = head;
    while(ptr) {
        PLNode next = ptr->next;
        free_node(ptr);
        ptr = next;
    }
}

#endif